<?php
/**
 * 安全许可证验证服务器
 * 实现服务端授权验证，防止客户端绕过
 * 强制使用数据库验证和加密通信
 */

// 尝试加载 WordPress 以使用 $wpdb
if (!defined('ABSPATH')) {
    $current = dirname(__FILE__);
    $found_wp = false;
    for ($i = 0; $i < 6; $i++) { // 向上最多 6 层
        if (file_exists($current . '/wp-load.php')) {
            define('ABSPATH', rtrim($current, '/') . '/');
            require_once(ABSPATH . 'wp-load.php');
            $found_wp = true;
            break;
        }
        $current = dirname($current);
    }
    if (!$found_wp) {
        error_log('[SpiderAuth] WordPress not found, cannot use $wpdb');
        http_response_code(500);
        echo json_encode(['success' => false, 'message' => 'WordPress not found']);
        exit;
    }
}

// 检查 $wpdb 是否可用
if (!isset($GLOBALS['wpdb']) || !$GLOBALS['wpdb']) {
    error_log('[SpiderAuth] WordPress database not available');
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Database not available']);
    exit;
}

header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type');

// 处理预检请求
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    http_response_code(200);
    exit;
}

// 只允许POST请求
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['success' => false, 'message' => 'Method not allowed']);
    exit;
}

// 获取请求数据（同时兼容简化模式）
$input = file_get_contents('php://input');
$data = json_decode($input, true);
if (!$data) { $data = []; }

// 简化模式：若直接携带 license_key + domain，则走简化校验流程（无需加密/签名/指纹）
if (!isset($data['encrypted_data']) && (isset($data['license_key']) || isset($_POST['license_key'])) && (isset($data['domain']) || isset($_POST['domain']))) {
    $license_key = $data['license_key'] ?? $_POST['license_key'];
    $domain = $data['domain'] ?? $_POST['domain'];
    $chart_type = $data['chart_type'] ?? $_POST['chart_type'] ?? 'response_time';
    $period = $data['period'] ?? $_POST['period'] ?? 'today';
    $action = $data['action'] ?? $_POST['action'] ?? '';

    // 先做许可证快速校验
    $result = simple_verify_license($license_key, $domain, $chart_type, $period);
    if (!$result['success']) {
        echo json_encode(array_merge($result, ['timestamp' => time(), 'server_id' => get_server_id()]));
        exit;
    }

    // 如果请求签发令牌，生成短期令牌并返回
    if ($action === 'issue_token') {
        $ttl = 7 * DAY_IN_SECONDS; // 默认7天
        // 统一使用域名 host 参与签名，确保与客户端校验一致
        $domain_host = parse_url($domain, PHP_URL_HOST);
        if (empty($domain_host)) {
            $domain_host = preg_replace('#^https?://#i', '', (string) $domain);
            $domain_host = preg_replace('#/.*$#', '', $domain_host);
        }
        $domain_host = strtolower(trim($domain_host));
        
        // 调试信息
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('[SpiderServer] Token generation debug:');
            error_log('  license_key: ' . $license_key);
            error_log('  domain: ' . $domain);
            error_log('  domain_host: ' . $domain_host);
            error_log('  chart_type: ' . $chart_type);
            error_log('  period: ' . $period);
        }
        
        $token = generate_access_token($license_key, $domain_host, $chart_type, $period, $ttl);
        if (!$token) {
            echo json_encode(['success' => false, 'message' => 'Token generation failed']);
            exit;
        }
        // 将令牌持久化到远程服务端数据表（若存在）
        if (function_exists('get_option')) {
            global $wpdb;
            $activations_table = $wpdb->prefix . 'spider_license_activations';
            // 如果表存在令牌相关列，则保存/更新当前域名的令牌
            $has_col = $wpdb->get_var($wpdb->prepare("SHOW COLUMNS FROM {$activations_table} LIKE 'access_token'"));
            if ($has_col) {
                // 规范化域名
                $domain_host = parse_url($domain, PHP_URL_HOST);
                if (empty($domain_host)) {
                    $domain_host = preg_replace('#^https?://#i', '', (string) $domain);
                    $domain_host = preg_replace('#/.*$#', '', $domain_host);
                }
                $domain_host = strtolower(trim($domain_host));
                $expires_at = date('Y-m-d H:i:s', time() + $ttl);
                // 同时尝试按 host、原始传值及常见变体更新，避免历史记录不一致
                $candidates = array_unique([
                    $domain_host,
                    $domain,
                    'https://' . $domain_host,
                    'http://' . $domain_host,
                    rtrim('https://' . $domain_host, '/') . '/',
                    rtrim('http://' . $domain_host, '/') . '/',
                    rtrim((string)$domain, '/'),
                    rtrim((string)$domain, '/') . '/',
                ]);
                foreach ($candidates as $domKey) {
                    // 优先使用 license_key + domain 精确匹配，避免误更新到其他许可证的记录
                    $exists_pair = (int)$wpdb->get_var($wpdb->prepare(
                        "SELECT COUNT(*) FROM {$activations_table} WHERE domain = %s AND license_key = %s",
                        $domKey, $license_key
                    ));
                    if ($exists_pair > 0) {
                        $wpdb->update($activations_table, [
                            'access_token' => $token['token'],
                            'token_issued_at' => current_time('mysql'),
                            'token_expires_at' => $expires_at,
                            'token_status' => 'active'
                        ], [ 'domain' => $domKey, 'license_key' => $license_key ]);
                        continue;
                    }
                    // 回退：仅按 domain 匹配（历史数据无 license_key 时）
                    $exists = (int)$wpdb->get_var($wpdb->prepare(
                        "SELECT COUNT(*) FROM {$activations_table} WHERE domain = %s",
                        $domKey
                    ));
                    if ($exists > 0) {
                        $wpdb->update($activations_table, [
                            'access_token' => $token['token'],
                            'token_issued_at' => current_time('mysql'),
                            'token_expires_at' => $expires_at,
                            'token_status' => 'active'
                        ], [ 'domain' => $domKey ]);
                    }
                }
            }
        }
        // 调试输出（仅 WP_DEBUG 时）：在响应头打印令牌片段，并写入 error_log
        if (defined('WP_DEBUG') && WP_DEBUG) {
            $token_preview = substr($token['token'], 0, 80) . '...';
            @header('X-Spider-Token-Debug: ' . $token_preview);
            @error_log('[SpiderAuth][issue_token] token=' . $token_preview . ' ttl=' . $ttl . ' alg=' . ($token['alg'] ?? ''));
        }
        $resp = [
            'success' => true,
            'message' => 'token issued',
            'token' => $token['token'],
            'ttl' => $ttl,
            'timestamp' => $token['t'],
            'signature' => $token['signature'],
            'alg' => $token['alg'],
            'server_id' => get_server_id()
        ];
        echo json_encode($resp);
        exit;
    }

    // 否则返回简化验证结果
    echo json_encode(array_merge($result, ['timestamp' => time(), 'server_id' => get_server_id()]));
    exit;
}

// 标准模式：需要加密数据
if (!$data || !isset($data['encrypted_data'])) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Invalid request data']);
    exit;
}

// 强制解密请求数据
$auth_data = decrypt_request_data($data['encrypted_data']);
if (!$auth_data) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Failed to decrypt request data']);
    exit;
}

// 强制验证请求签名
if (!verify_request_signature($auth_data)) {
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Invalid request signature']);
    exit;
}

// 验证时间戳（防止重放攻击）
$current_time = time();
$request_time = $auth_data['timestamp'];
if (abs($current_time - $request_time) > 300) { // 5分钟有效期
    http_response_code(400);
    echo json_encode(['success' => false, 'message' => 'Request expired']);
    exit;
}

// 记录验证请求
log_verification_request($auth_data, 'processing');

// 验证硬件指纹和域名
$verification_result = verify_license_and_domain($auth_data);

// 记录验证结果
log_verification_request($auth_data, $verification_result['success'] ? 'success' : 'failed', $verification_result['message']);

// 生成响应签名
$response_data = array_merge($verification_result, [
    'timestamp' => time(),
    'server_id' => get_server_id()
]);

$response_data['signature'] = generate_response_signature($response_data, $auth_data['secret_key'] ?? '');

echo json_encode($response_data);

/**
 * 解密请求数据
 */
function decrypt_request_data($encrypted_data) {
    $private_key = get_private_key();
    if (!$private_key) {
        return false;
    }
    
    $encrypted = base64_decode($encrypted_data);
    $decrypted = '';
    
    if (!openssl_private_decrypt($encrypted, $decrypted, $private_key)) {
        return false;
    }
    
    return json_decode($decrypted, true);
}

/**
 * 验证请求签名
 */
function verify_request_signature($auth_data) {
    $expected_signature = generate_expected_signature($auth_data);
    return hash_equals($expected_signature, $auth_data['signature']);
}

/**
 * 生成期望的签名
 */
function generate_expected_signature($auth_data) {
    // 使用客户端传来的站点密钥进行签名校验，确保与客户端生成方式一致
    $client_secret = $auth_data['secret_key'] ?? '';
    $signature_data = [
        'chart_type' => $auth_data['chart_type'],
        'period' => $auth_data['period'],
        'timestamp' => $auth_data['timestamp'],
        'nonce' => $auth_data['nonce'],
        'hardware_fingerprint' => $auth_data['hardware_fingerprint'],
        'secret_key' => $client_secret
    ];
    
    return hash('sha256', serialize($signature_data));
}

/**
 * 验证许可证和域名 - 基于你的表结构，使用 $wpdb
 */
function verify_license_and_domain($auth_data) {
    global $wpdb;
    
    $domain = $auth_data['domain'];
    $hardware_fingerprint = $auth_data['hardware_fingerprint'];
    $chart_type = $auth_data['chart_type'];
    $period = $auth_data['period'];
    
    try {
        // 1. 查找许可证激活记录
        $activations_table = $wpdb->prefix . 'spider_license_activations';
        $licenses_table = $wpdb->prefix . 'spider_licenses';
        
        $activation_record = $wpdb->get_row($wpdb->prepare("
            SELECT la.*, l.license_key, l.plan, l.features, l.expires_at, l.max_domains
            FROM {$activations_table} la
            JOIN {$licenses_table} l ON la.license_id = l.id
            WHERE la.domain = %s AND la.status = 'active'
        ", $domain), ARRAY_A);
        
        if (!$activation_record) {
            return [
                'success' => false,
                'message' => '域名未授权：' . $domain
            ];
        }
        
        // 2. 检查许可证是否过期
        if ($activation_record['expires_at'] && strtotime($activation_record['expires_at']) < time()) {
            return [
                'success' => false,
                'message' => '许可证已过期'
            ];
        }
        
        // 3. 检查或创建硬件指纹记录
        $fingerprints_table = $wpdb->prefix . 'spider_hardware_fingerprints';
        
        $fingerprint_record = $wpdb->get_row($wpdb->prepare(
            "SELECT * FROM {$fingerprints_table} WHERE license_activation_id = %d AND fingerprint = %s",
            $activation_record['id'], $hardware_fingerprint
        ), ARRAY_A);
        
        if (!$fingerprint_record) {
            // 创建新的硬件指纹记录
            $wpdb->insert(
                $fingerprints_table,
                [
                    'license_activation_id' => $activation_record['id'],
                    'fingerprint' => $hardware_fingerprint,
                    'fingerprint_data' => json_encode($auth_data),
                    'created_at' => current_time('mysql'),
                    'last_verified' => current_time('mysql'),
                    'verification_count' => 1
                ],
                ['%d', '%s', '%s', '%s', '%s', '%d']
            );
        } else {
            // 更新验证次数和最后验证时间
            $wpdb->update(
                $fingerprints_table,
                [
                    'last_verified' => current_time('mysql'),
                    'verification_count' => $fingerprint_record['verification_count'] + 1
                ],
                ['id' => $fingerprint_record['id']],
                ['%s', '%d'],
                ['%d']
            );
        }
        
        // 4. 解析功能权限
        $features = json_decode($activation_record['features'], true) ?: [];
        
        // 5. 检查特定功能权限
        if ($chart_type === 'response_time' && !($features['response_time_analysis'] ?? false)) {
            return [
                'success' => false,
                'message' => '响应时间分析功能需要激活PRO版本'
            ];
        }
        
        // 仅限制 7天/30天；今天/昨天免费
        if (in_array($period, ['week', 'month']) && !($features['extended_time_ranges'] ?? false)) {
            return [
                'success' => false,
                'message' => '7天和30天数据查看需要激活PRO版本'
            ];
        }
        
        // 6. 更新激活记录的最后检查时间
        $wpdb->update(
            $activations_table,
            ['last_check' => current_time('mysql')],
            ['id' => $activation_record['id']],
            ['%s'],
            ['%d']
        );
        
        // 7. 记录验证日志
        log_verification_request($auth_data, $activation_record['id'], 'success', '授权验证成功');
        
        return [
            'success' => true,
            'message' => '授权验证成功',
            'features' => $features,
            'license_info' => [
                'plan' => $activation_record['plan'],
                'expires_at' => $activation_record['expires_at'],
                'license_key' => $activation_record['license_key']
            ]
        ];
        
    } catch (Exception $e) {
        error_log('[SpiderAuth] Database error in verify_license_and_domain: ' . $e->getMessage());
        // 记录失败日志
        log_verification_request($auth_data, null, 'failed', '数据库验证失败：' . $e->getMessage());
        return [
            'success' => false,
            'message' => '数据库验证失败，请稍后重试'
        ];
    }
}

/**
 * 简化版校验：直接用 license_key + domain 进行快速校验
 */
function simple_verify_license($license_key, $domain, $chart_type = 'response_time', $period = 'today') {
    global $wpdb;
    $licenses_table = $wpdb->prefix . 'spider_licenses';
    $activations_table = $wpdb->prefix . 'spider_license_activations';

    // 获取许可证
    $license = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$licenses_table} WHERE license_key = %s", $license_key), ARRAY_A);
    if (!$license) {
        return ['success' => false, 'message' => '许可证无效'];
    }
    // 检查过期
    if (!empty($license['expires_at']) && strtotime($license['expires_at']) < time()) {
        return ['success' => false, 'message' => '许可证已过期'];
    }
    // 检查是否有该域名的激活（如无则放宽：只要许可证存在也允许）
    $activated = (int)$wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$activations_table} WHERE license_id = %d AND domain = %s AND status='active'", $license['id'], $domain)) > 0;
    if (!$activated) {
        // 若未找到域名记录，尝试为该域名创建一条激活（简化模式默认允许同域重复使用）
        $wpdb->insert($activations_table, [
            'license_id' => $license['id'],
            'domain' => $domain,
            'status' => 'active',
            'activated_at' => current_time('mysql'),
            'last_check' => current_time('mysql'),
            'license_key' => $license_key
        ], ['%d','%s','%s','%s','%s','%s']);
    } else {
        $wpdb->update($activations_table, ['last_check' => current_time('mysql')], ['license_id' => $license['id'], 'domain' => $domain], ['%s'], ['%d','%s']);
    }

    // 功能开关（features 字段为 JSON，缺省视为全开）
    $features = json_decode($license['features'] ?? '[]', true);
    if ($chart_type === 'response_time' && isset($features['response_time_analysis']) && !$features['response_time_analysis']) {
        return ['success' => false, 'message' => '响应时间分析功能需要激活PRO版本'];
    }
    if (in_array($period, ['week','month']) && isset($features['extended_time_ranges']) && !$features['extended_time_ranges']) {
        return ['success' => false, 'message' => '7天和30天数据查看需要激活PRO版本'];
    }

    return [
        'success' => true,
        'message' => '授权验证成功(简化)',
        'features' => $features,
        'license_info' => [
            'plan' => $license['plan'] ?? 'basic',
            'expires_at' => $license['expires_at'] ?? null,
            'license_key' => $license['license_key']
        ]
    ];
}

/**
 * 生成访问令牌（优先RSA签名，回退HMAC）
 * token 结构：base64(json:{t,exp,feat,per,dom,alg,sign})
 */
function generate_access_token($license_key, $domain, $feature, $period, $ttl) {
    $now = time();
    $exp = $now + max(60, (int)$ttl);
    $payload = [
        't' => $now,
        'exp' => $exp,
        'feat' => $feature,
        'per' => $period,
        'dom' => $domain,
    ];
    // 规范化域名：与服务端激活时保持一致
    $domain_host = wp_parse_url($domain, PHP_URL_HOST);
    if (empty($domain_host)) {
        // 兜底：去除协议和路径，仅保留主机名
        $domain_host = preg_replace('#^https?://#i', '', (string) $domain);
        $domain_host = preg_replace('#/.*$#', '', $domain_host);
    }
    $domain_host = strtolower(trim($domain_host));
    $marker = substr(hash('sha256', $license_key . '|' . $domain_host), 0, 12);
    $toSign = $payload['t'] . '|' . $payload['exp'] . '|' . $payload['feat'] . '|' . $payload['per'] . '|' . $marker;

    $private = get_private_key();
    if ($private && function_exists('openssl_sign')) {
        $signature = '';
        if (!openssl_sign($toSign, $signature, $private, OPENSSL_ALGO_SHA256)) {
            return false;
        }
        $alg = 'RS256';
        $packed = [
            't' => $payload['t'],
            'exp' => $payload['exp'],
            'feat' => $payload['feat'],
            'per' => $payload['per'],
            'alg' => $alg,
            'sign' => base64_encode($signature)
        ];
        return [
            'token' => base64_encode(json_encode($packed)),
            't' => $now,
            'signature' => base64_encode($signature),
            'alg' => $alg
        ];
    }
    // 生产模式：严格要求 RS256，不再回退 HS256
    if (defined('WP_DEBUG') && WP_DEBUG) {
        @error_log('[SpiderAuth] RS256 private key not available; token issuance aborted');
    }
    return false;
}

/**
 * 记录验证请求日志
 */
function log_verification_request($auth_data, $license_activation_id, $status, $message) {
    global $wpdb;
    
    try {
        $logs_table = $wpdb->prefix . 'spider_verification_logs';
        
        $wpdb->insert(
            $logs_table,
            [
                'request_id' => $auth_data['request_id'],
                'license_activation_id' => $license_activation_id,
                'chart_type' => $auth_data['chart_type'],
                'period' => $auth_data['period'],
                'status' => $status,
                'message' => $message,
                'ip_address' => $auth_data['server_ip'] ?? $_SERVER['REMOTE_ADDR'] ?? '',
                'user_agent' => $auth_data['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'] ?? '',
                'verified_at' => current_time('mysql')
            ],
            ['%s', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s']
        );
    } catch (Exception $e) {
        error_log('[SpiderAuth] Failed to log verification request: ' . $e->getMessage());
    }
}

/**
 * 生成响应签名
 */
function generate_response_signature($response_data, $client_secret) {
    // 用客户端密钥生成响应签名，客户端将用相同密钥校验
    $timestamp = $response_data['timestamp'];
    $secret_key = $client_secret ?: get_server_secret_key();
    return hash('sha256', $timestamp . $secret_key);
}

/**
 * 获取私钥
 */
function get_private_key() {
    $key_file = __DIR__ . '/keys/private_key.pem';
    if (!file_exists($key_file)) {
        return false;
    }
    return file_get_contents($key_file);
}

/**
 * 获取服务器密钥
 */
function get_server_secret_key() {
    return 'your-server-secret-key-here'; // 实际使用时应该从安全位置获取
}

/**
 * 获取服务器ID
 */
function get_server_id() {
    return 'spider-monitor-auth-server-001';
}

/**
 * 获取授权域名列表
 */
function get_authorized_domains() {
    // 实际使用时应该从数据库获取
    return [
        'zibovip.top',
        'localhost',
        '127.0.0.1'
    ];
}

/**
 * 获取存储的硬件指纹
 */
function get_stored_fingerprint($domain) {
    // 实际使用时应该从数据库获取
    $fingerprints = [
        'zibovip.top' => 'stored-fingerprint-hash-here'
    ];
    return $fingerprints[$domain] ?? null;
}

/**
 * 获取许可证状态
 */
function get_license_status($domain) {
    // 实际使用时应该从数据库获取
    return [
        'active' => true,
        'expires_at' => strtotime('+1 year'),
        'plan' => 'pro'
    ];
}

// 注意：上方已实现基于 $wpdb 的 log_verification_request()，此处删除重复定义以避免致命错误
?>
